home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 3 / Your Choice Software Collection 3.iso / prgmming / swag08 / drives.swg < prev    next >
Text File  |  1994-09-22  |  27KB  |  1 lines

  1. SWAGOLX.EXE (c) 1993 GDSOFT  ALL RIGHTS RESERVED 00010                                                                           1      08-24-9413:27ALL                      PAUL WEST                CD-ROM Dectection        SWAG9408    v6D@    51     ╣   {π JM>Would you happen to have any example code to determine if a drive is aπ JM>hard disk, cd-rom, ramdrive etc. ?ππHere is a unit that will at least tell you a little about the CD-ROM.   Not allπMSCDEX functions are implemented, but enough to identify the CD-ROMS.π}πunit CDROM;ππ{$X+}   { Extended Syntax Rules }ππinterfaceππtypeπ  CDR_DL_ENTRY = recordπ    UNITNO  : byte;π    OFFSET  : word;π    SEGMENT : word;π  end;ππ  CDR_DL_BUFFER   = array[1..26] of CDR_DL_ENTRY;π  CDR_DRIVE_UNITS = array[0..25] of byte;π  CDR_VTOC        = array[1..2048] of byte;ππ{ 00h } procedure CDR_GET_DRIVE_COUNT   (var COUNT, FIRST: word);π{ 01h } procedure CDR_GET_DRIVE_LIST    (var LIST: CDR_DL_BUFFER);π{ 02h } function  CDR_GET_COPR_NAME     (DRIVE: byte): string;π{ 03h } function  CDR_GET_ABSTRACT_NAME (DRIVE: byte): string;π{ 04h } function  CDR_GET_BIBLIO_NAME   (DRIVE: byte): string;π{ 05h Read VTOC }π{ 06h Reserved }π{ 07h Reserved }π{ 08h Absolute Disk Read }π{ 09h Absolute Disk Write }π{ 0ah Reserved }π{ 0bh } function  CDR_DRIVE_CHECK       (DRIVE: byte): boolean;π{ 0ch } function  CDR_VERSION: word;π{ 0dh } procedure CDR_GET_DRIVE_UNITS   (var BUFFER: CDR_DRIVE_UNITS);π{ 0eh Get or Set VDR }π{ 0fh Get Dir Entry }π{ 10h Send Device Request }ππimplementationππuses dos, strings;ππconstπ  CDROM_INTERRUPT = $2f;ππvarπ  REG : registers;ππprocedure CDR_GET_DRIVE_COUNT (var COUNT, FIRST: word);πassembler;ππ{ Returns the total number of CD-ROM Drives in the system }π{ and the logical drive number of the first drive.        }ππ{ In a system that contains multiple CD-ROM Drives and is }π{ also networked, the CD-ROM drives might not be assigned }π{ as consecutive logical units.  See also MSCDEX Function }π{ 0Dh (Get CD-ROM Drive Letters)                          }ππasmπ  mov ax, 1500hπ  xor bx, bxπ  int CDROM_INTERRUPTπ  les di, COUNTπ  mov es:[di], bxπ  les di, FIRSTπ  mov es:[di], cxπend;ππprocedure CDR_GET_DRIVE_LIST (var LIST: CDR_DL_BUFFER);πassembler;ππ{ Returns a driver unit identifier for each CD-ROM drive  }π{ in the system, along with the address of the header for }π{ the device driver that controls the drive.              }ππ{ The driver unit code returned in the buffer is not the  }π{ systemwide logical drive identifier but is the relative }π{ unit for that particular driver.  For example if three  }π{ CD-ROM drivers are installed, each supporting one phy-  }π{ sical drive, the driver unit code in each 5 byte entry  }π{ will be 0.  The systemwide drive identifiers for each   }π{ CD-ROM unit can be obtained with MSCDEX Function 0Dh    }π{ (Get CD-ROM Drive Letters).                             }ππasmπ  mov ax, 1501hπ  les bx, LISTπ  int CDROM_INTERRUPTπend;ππfunction  CDR_GET_COPR_NAME (DRIVE: byte): string;ππ{ Returns the name of the copyright file from the volume  }π{ table of contents (VTOC) of the specified CD-ROM Drive. }ππ{ CD-ROM Specs allow for a 31 character filename followed }π{ by a semicolon (;) and a 5 digit version number.        }ππ{ On disks that comply with the High Sierra standard,     }π{ the filename has an MS-DOS compatable (8/3) format.     }ππvarπ  BUFFER : array[0..38] of char;ππbeginπ  REG.AX := $1502;π  REG.CX := DRIVE;π  REG.ES := seg(BUFFER);π  REG.BX := ofs(BUFFER);π  intr(CDROM_INTERRUPT, REG);π  CDR_GET_COPR_NAME := strpas(BUFFER);πend;ππfunction  CDR_GET_ABSTRACT_NAME (DRIVE: byte): string;ππ{ Returns the name of the abstract file from the volume   }π{ table of contents (VTOC) for the specified CD-ROM drive.}ππ{ CD-ROM Specs allow for a 31 character filename followed }π{ by a semicolon (;) and a 5 digit version number.        }ππ{ On disks that comply with the High Sierra standard,     }π{ the filename has an MS-DOS compatable (8/3) format.     }ππvarπ  BUFFER : array[0..38] of char;ππbeginπ  REG.AX := $1503;π  REG.CX := DRIVE;π  REG.ES := seg(BUFFER);π  REG.BX := ofs(BUFFER);π  intr(CDROM_INTERRUPT, REG);π  CDR_GET_ABSTRACT_NAME := strpas(BUFFER);πend;ππfunction  CDR_GET_BIBLIO_NAME (DRIVE: byte): string;ππ{ Returns the name if the bibliographic file from the     }π{ volume table of contents (VTOC) for the specified drive.}ππ{ CD-ROM Specs allow for a 31 character filename followed }π{ by a semicolon (;) and a 5 digit version number.        }ππ{ This function is provided for compatability with the    }π{ ISO-9660 standard.  A null string is returned for disks }π{ complying with the High Sierra standard.                }ππvarπ  BUFFER : array[0..38] of char;ππbeginπ  REG.AX := $1504;π  REG.CX := DRIVE;π  REG.ES := seg(BUFFER);π  REG.BX := ofs(BUFFER);π  intr(CDROM_INTERRUPT, REG);π  CDR_GET_BIBLIO_NAME := strpas(BUFFER);πend;ππfunction CDR_DRIVE_CHECK (DRIVE: byte): boolean;ππ{ Returns a code indicating whether a particular logical  }π{ unit is supported by the Microsoft CD-ROM Extensions    }π{ module (MSCDEX).                                        }ππbeginπ  REG.AX := $150b;π  REG.BX := $0000;π  REG.CX := DRIVE;π  intr(CDROM_INTERRUPT, REG);π  CDR_DRIVE_CHECK := (REG.AX <> $0000) and (REG.BX = $adad);πend;ππfunction  CDR_VERSION: word;ππ{ Returns the version number of the Microsoft CD-ROM Extensions }ππ{ The Major Version number is returned in the High Order byte   }π{ and the Minor Version Number is returned in the Lo order      }π{ byte.  IE if the MSCDEX Version is 2.10, this routine will    }π{ return $0210.                                                 }ππbeginπ  REG.AX := $150c;π  REG.BX := $0000;π  intr(CDROM_INTERRUPT, REG);ππ  { Version 1.0 Returns 0 instead of actual Version Number }π  { So we will fix it so that this routine returns 1.0     }ππ  if REG.BX = 0 then beginπ    CDR_VERSION := $0100;π  end else beginπ    CDR_VERSION := REG.BX;π  end;πend;ππprocedure CDR_GET_DRIVE_UNITS(var BUFFER: CDR_DRIVE_UNITS);πassembler;ππ{ Returns a list of the systemwide logical drive identifers     }π{ that are assigned to CD-ROM drives.                           }ππ{ Upon return the buffer contains a series of 1 byte entries.   }π{ Each entry is a logical unit code assigned to a CD-ROM drive  }π{ (0 = A, 1 = B, etc); the units might not be consecutive.      }ππ{ The number of valid entries can be determined by MSCDEX       }π{ function 00h.                                                 }ππasmπ  mov ax, 150dhπ  les bx, BUFFERπ  int CDROM_INTERRUPTπend;ππend.π                                                                                                2      08-24-9413:28ALL                      OLAF GREIS               CD-ROM Detection         SWAG9408    LDPα    6      ╣   {πQ: How do I detect, a certain drive is a CD-Rom?ππA: The foolowing function returns True if the drive is a CD-ROM.π}ππ   Uses DOS;π   FUNCTION Is_CDROM(Drv : Char):BOOLEAN;π   VAR R  : Registers;π       CDR: string;π       cnt: byte;π   BEGINπ     Is_CDROM := false;π     CDR      := '';π     WITH R DOπ       BEGINπ         AX := $1500;π         BX := $0000;π         CX := $0000;π         Intr( $2F, R );π         IF BX > 0 THENπ           BEGINπ             FOR cnt := 0 TO (bx-1) DOπ             CDR := CDR +CHAR( CL + Byte('A') + cnt );π           END;π         Is_CDROM := POS( upcase(Drv), CDR ) > 0π       ENDπ   END;π            3      08-24-9413:30ALL                      TURBO POWER              DPMI Read/Write Sectors  SWAG9408    ▀╙uv    53     ╣   {$S-,R-,V-,I-,B-,F+,O+,A-,X+}ππunit DDisk;π  {-Read and write absolute sectors using DOS int $25 and $26π    in protected mode under DOS or Windows. Does not support real mode.π    Requires BP7 or TPW 1.5.ππ    Based on the code in the OPDOS unit from Object Professional.ππ    Thanks to Maynard Riley and Mark Boler for work done on this unit.ππ    Notes:π      The calling parameters correspond to those in OPDOS.π      Drive = 0 corresponds to drive A.π      Sectors are typically 512 bytes each. NumSects*SectorSize must beπ        less than 64K.π      Buf may be any buffer in a protected mode program. DDISKπ        temporarily allocates a DOS real mode buffer, then copiesπ        the result into or out of Buf.π      If the function returns False, the DosError variable from theπ        DOS or WINDOS unit may have a non-zero value with more informationπ        about the failure.ππ      Use DPMIWriteDiskSectors with caution!ππ    Version 1.0 (first public release) 7/19/94ππ    For more information, contact TurboPower Softwareπ    CompuServe 76004,2611π  }ππinterfaceππfunction DPMIReadDiskSectors(Drive : Word;π                             FirstSect : LongInt; NumSects : Word;π                             var Buf) : Boolean;π  {-Read sectors using int $25}ππfunction DPMIWriteDiskSectors(Drive : Word;π                              FirstSect : LongInt; NumSects : Word;π                              var Buf) : Boolean;π  {-Write sectors using int $26}ππ  {====================================================================}ππimplementationππusesπ{$IFDEF DPMI}π  DOS,π{$ELSE}π  WinDOS,π{$ENDIF}π  WinAPI;ππtypeπ  DpmiRealBuf =π    objectππ    privateπ      Bytes   : LongInt;π      BufBase : LongInt;ππ    publicπ      constructor Init(BufBytes : LongInt);π      destructor Done;π      function Size : LongInt;π      function Segment : Word;π      function Selector : Word;π      function RealPtr : Pointer;π      function ProtPtr : Pointer;π    end;ππ  DPMIRegisters =π    recordπ      DI : LongInt;π      SI : LongInt;π      BP : LongInt;π      Reserved : LongInt;π      BX : LongInt;π      DX : LongInt;π      CX : LongInt;π      AX : LongInt;π      Flags : Word;π      ES : Word;π      DS : Word;π      FS : Word;π      GS : Word;π      IP : Word;π      CS : Word;π      SP : Word;π      SS : Word;π    end;ππ  PacketPtr = ^PacketRec;π  PacketRec =π    recordπ      StartLo : Word;π      StartHi : Word;π      Count : Word;π      BufOfs : Word;π      BufSeg : Word;π    end;ππ  procedure GetRealModeIntVector(IntNo : Byte; var Vector : Pointer); assembler;π  asmπ    mov     ax,0200hπ    mov     bl,IntNoπ    int     31hπ    les     di,Vectorπ    mov     word ptr es:[di],dxπ    mov     word ptr es:[di+2],cxπ  end;ππ  function CallFarRealModeProc(var Regs : DPMIRegisters) : Word; assembler;π  asmπ    mov     ax,0301hπ    xor     bx,bxπ    xor     cx,cxπ    les     di,Regsπ    int     31hπ    jc      @@9π    xor     ax,axπ@@9:π  end;ππ  function DpmiRealBuf.Segment : Word;π  beginπ    Segment := BufBase shr 16;π  end;ππ  function DpmiRealBuf.Selector : Word;π  beginπ    Selector := BufBase and $FFFF;π  end;ππ  function DpmiRealBuf.RealPtr : Pointer;π  beginπ    RealPtr := Ptr(BufBase shr 16, 0);π  end;ππ  function DpmiRealBuf.ProtPtr : Pointer;π  beginπ    ProtPtr := Ptr(BufBase and $FFFF, 0);π  end;ππ  function DpmiRealBuf.Size : LongInt;π  beginπ    Size := Bytes;π  end;ππ  constructor DpmiRealBuf.Init(BufBytes : LongInt);π  beginπ    BufBase := GlobalDosAlloc(BufBytes);π    if BufBase = 0 thenπ      Fail;π    Bytes := BufBytes;π  end;ππ  destructor DpmiRealBuf.Done;π  beginπ    GlobalDosFree(Selector);π  end;ππtypeπ  DiskInfoRec =π    objectπ      DriveNumber : Byte;π      ClustersAvailable : Word;π      TotalClusters : Word;π      BytesPerSector : Word;π      SectorsPerCluster : Word;π      constructor Init(d : Byte);π    end;ππ  constructor DiskInfoRec.Init(d : Byte);π  varπ    Ok : Boolean;π  beginπ    DriveNumber := d; { 0 = default ; 1 = 'A' }ππ    asmπ      mov     dl,dπ      mov     ah,$36π      int     $21π      cmp     ax,$FFFFπ      je      @8ππ      les     di,Selfπ      mov     es:[di].SectorsPerCluster,axπ      mov     es:[di].ClustersAvailable,bxπ      mov     es:[di].BytesPerSector,cxπ      mov     es:[di].TotalClusters,dxπ      mov     al,Trueπ      jmp     @9ππ@8:   mov     al,Falseπ@9:   mov     Ok,alπ    end;ππ    if not Ok thenπ      Fail;π  end;ππ  function DPMIReadWrite(Drive : Word;π                         FirstSect : LongInt; NumSects : Word;π                         var Buf; Vector : Byte) : Boolean;π  varπ    SaveInt : Pointer;π    Status : Word;π    BufBytes : LongInt;π    DiskInfo : DiskInfoRec;π    InterimBuf : DpmiRealBuf;π    PacketBuf : DpmiRealBuf;π    Regs : DPMIRegisters;π  beginπ    DosError := 0;π    DPMIReadWrite := False;ππ    if not DiskInfo.Init(Drive+1) thenπ      Exit;ππ    BufBytes := LongInt(NumSects)*DiskInfo.BytesPerSector;π    if BufBytes > 65535 thenπ      Exit;π    if not InterimBuf.Init(BufBytes) thenπ      Exit;ππ    if not PacketBuf.Init(SizeOf(PacketRec)) then beginπ      InterimBuf.Done;π      Exit;π    end;ππ    if Vector = $26 thenπ      Move(Buf, InterimBuf.ProtPtr^, BufBytes);ππ    FillChar(Regs, SizeOf(Regs), 0);π    with PacketPtr(PacketBuf.ProtPtr)^ do beginπ      StartLo := FirstSect and $FFFF;π      StartHi := FirstSect shr 16;π      Count := NumSects;π      BufOfs := 0;π      BufSeg := InterimBuf.Segment;π    end;ππ    GetRealModeIntVector(Vector, SaveInt); { returns real mode seg:ofs }π    with Regs do beginπ      CX := $FFFF;π      AX := Drive;π      BX := 0;π      DS := PacketBuf.Segment;π      CS := LongInt(SaveInt) shr 16;π      IP := LongInt(SaveInt) and $FFFF;π    end;π    Status := CallFarRealModeProc(Regs);ππ    if Status = 0 thenπ      if Odd(Regs.Flags) thenπ        DosError := Regs.AXπ      else beginπ        if Vector = $25 thenπ          Move(InterimBuf.ProtPtr^, Buf, BufBytes);π        DPMIReadWrite := True;π      end;ππ    PacketBuf.Done;π    InterimBuf.Done;π  end;ππ  function DPMIReadDiskSectors(Drive : Word;π                               FirstSect : LongInt; NumSects : Word;π                               var Buf) : Boolean;π  beginπ    DPMIReadDiskSectors := DPMIReadWrite(Drive, FirstSect, NumSects, Buf, $25);π  end;ππ  function DPMIWriteDiskSectors(Drive : Word;π                                FirstSect : LongInt; NumSects : Word;π                                var Buf) : Boolean;π  beginπ    DPMIWriteDiskSectors := DPMIReadWrite(Drive, FirstSect, NumSects, Buf, $26);π  end;ππend.π                                                                                          4      08-24-9413:31ALL                      MAYNARD PHILBROOK        Disk-detecting routine   SWAG9408    ≈╩vÿ    6      ╣   {π -=> Quoting Christian Proehl to All <=-ππ CP> Subject: Disk-detecting routines without DOS (andππ CP> Muelheim, den 20.05.94ππ CP> Hello!ππ CP> I have problem I don't know how to solve it.π CP> Perhaps someone around the world knows more, please help me!ππ use the bios callππ  function $16, int $13π}ππfunction DiskChange( DriveNmber :Byte) :Boolean;πBeginπ ASmπ   Mov AH, $16π   Mov DL, driveNmberπ   Int $13π   Mov AL,AH;  { use AL & AH as a Return Value }π End;πEnd;ππBeginπ  If DiskChange(0) then Write(' Disk has Changed in Drive ''A'' ')π   Elseπ     Write(' Disk Has changed ');πend.π                                             5      08-24-9413:32ALL                      ANDREW EIGUS             Drive Detection          SWAG9408    ?╚û    11     ╣   {π SA> Does anyone have any idea of how I can check the system hardware andπ SA> identify available hard drives and disk drives?π}ππππconstπ  { GetDriveType return values.  REQUIRES DOS 3.x or greater}ππ  dtError     = 0; { Drive physically isn't available }π  dtRemote    = 1; { Remote (network) disk drive }π  dtFixed     = 2; { Fixed (hard) disk drive }π  dtRemovable = 3; { Removable (floppy) disk drive }π  dtBadVer    = $FF; { Invalid DOS version (DOS 3.x required) }πππFunction GetDriveType(Drive : byte) : byte; assembler;πAsmπ  MOV AH,30hπ  INT 21hπ  CMP AL,3π  JGE @@1π  MOV AL,dtBadVerπ  JMP @@4π@@1:π  MOV BL,Driveπ  MOV AX,4409hπ  INT 21hπ  JNC @@2π  MOV AL,dtErrorπ  JMP @@5π@@2:π  CMP AL,Trueπ  JNE @@3π  MOV AL,dtRemoteπ  JMP @@5π@@3:π  MOV AX,4408hπ  INT 21hπ  CMP AL,Trueπ  JNE @@4π  MOV AL,dtFixedπ  JMP @@5π@@4:π  MOV AL,dtRemovableπ@@5:πEnd; { GetDriveType }ππvarπ  Drive : byte;π  DT : byte;ππBeginπ  for Drive := 1 to 25 doπ  beginπ    DT := GetDriveType(Drive);π    if DT <> dtError thenπ    beginπ      Write('Drive ', Chr(Drive + 64), ': ');π      case DT ofπ        dtRemote: WriteLn('Network drive');π        dtFixed: WriteLn('Hard disk');π        dtRemovable: WriteLn('Floppy drive')π      endπ    endπ  endπEnd.ππ                                     6      08-24-9417:52ALL                      BJÖRN FELTEN             TRUENAME (BASM)          SWAG9408    ∞E    ò    10     ╣   {SWAG=DOS.SWG,BJÖRN FELTEN,TRUENAME (BASM)}ππ{ Updated DOS.SWG on August 24, 1994 }ππππprogram TName;  { to test the TrueName function }ππfunction TrueName(var P: string): string; assembler;π{ returns TrueName just like the DOS command does }π{ if error, returns a zero length string }π{ will probably crash for DOS versions < 3.0 }π{ donated to the Public Domain by Björn Felten @ 2:203/208 }πasmπ   push  dsπ   lds   si,Pπ@strip:π   inc   si     { skip length byte ... }π   cmp   byte ptr [si],' 'π   jle   @strip { ... and trailing white space }ππ   les   di,@Resultπ   inc   di     { leave room for byte count }π   mov   ah,60h { undocumented DOS call }π   int   21hπ   pop   dsπ   jc    @errorππ   mov   cx,80  { convert ASCIZ to Pascal string }π   xor   ax,axπ   repnz scasb  { find trailing zero }π   mov   ax,80π   sub   ax,cx  { get length byte }π   jmp   @retππ@error:π   xor   ax,ax  { return zero length string }ππ@ret:π   les   di,@Resultπ   stosbπend;πππvar S:string;πbeginπ   S:=paramstr(1);π   if paramcount<>1 thenπ      writeln('Usage: tname <filename>')π   elseπ      writeln('TrueName of ',S,' is ',TrueName(S))πend.π               7      08-24-9417:53ALL                      VARIOUS                  TrueName equivalent      SWAG9408    u╧    20     ╣   π{ This program uses a proc from my pascal library that I use to getπ  true names. Written and tested with tp4  should work with any tp andπ  dos 3.1+  gm 05/94 }πusesπ  dos;π  {--05/93 gary a. mays --}π  {  this procedure uses the undocumented dos function $60 to fetch theπ     canonical name of a file or path specification }π  procedure canonicalize(path: string; var canonical: string;π                          var stat: word);π    varπ      regs : registers;π      i : integer;π      bytes : byte absolute canonical;π  beginπ    with regs doπ    beginπ      stat := 0;π      ah := $60;π      path := path + chr(0); { convert to asciz }π      ds := seg(path[1]); { asciz name }π      si := ofs(path[1]);π      es := seg(canonical[1]);{ points to 128 byte result buffer }π      di := ofs(canonical[1]);{ result is asciz }π      msdos(regs); { returns canonical name: does not have to exist... }π      if flags and fcarry > 0 thenπ        stat := axπ      elseπ      beginπ        bytes := 0;π        while canonical[bytes + 1] <> #0 do inc(bytes); {conv to ascii}π        { not tested on a network - this test will fail on net drive }π        if canonical[2] <> ':' then { bad because of bad path }π          stat := 3;π      end;π    end;π  end; {canonicalize}ππ  varπ    stat : word;π    path : string;π    canonical : string;πbeginπ  if paramstr(1) = '' thenπ    path := '.'π  elseπ    path := paramstr(1);π  canonicalize(path, canonical, stat);π  case stat ofπ  0: writeln(canonical);π  2: writeln('Invalid path: ',path);π  3: writeln('Invalid drive or malformed path: ',path);π  else writeln('Status: ',stat,' for ',path);π  end; {case}πend.πππIL>  I'm looking for an equivalent to the DOS command TRUENAME. Here's anππprogram TruePath;πuses OpString,DOS;πvarπ  OldName, NewName : String;π  RegisterSet : Registers;πBeginπ  OldName:=ParamStr(1);π  OldName[Length(OldName)+1] := #0;π  NewName[0] := #0;π  With RegisterSet doπ  Beginπ    AH := $60;π    AL := 0;π    DS := Seg(OldName[1]);π    SI := Ofs(OldName[1]);π    ES := Seg(NewName[1]);π    DI := Ofs(NewName[1]);π  End;π  MsDos(RegisterSet);π  If Odd(RegisterSet.Flags) Thenπ    Writeln('Failure ',RegisterSet.AX) (* failure code *)π  Elseπ  Beginπ    NewName[0]:=#255;π    NewName[0]:=Chr(Pos(#0,NewName));π    Writeln(NewName);π  End;πEnd.π                                                                                                                             8      08-25-9409:06ALL                      MARTIN RICHARDSON        Getting Disk Type        SWAG9408        Iⁿû    12     ╣   {πMR│ How do you tell the difference between a fixed hard drive, and aπ  │ removable drive or network drive?  Why? I have a program which reportsππThis little demo program contains the answers for most of yourπquestions.πππ{ uses int $21, service $44, subservices 8 & 9  to get driveπ  existence, removeable/non-removeable, and local/remote status }ππuses dos;ππvar drive   : word;π    ts      : string[30];π    r       : registers;π    drexist : boolean;ππbeginπ      for drive := 1 to 26 doπ        beginπ          drexist := false;π          ts := 'unkn';ππ          r.ax := $4408;      { check for dos floppy/hard drv }π          r.bl := drive;π          msdos(r);π          if not odd(r.flags) then   { if not carry then ... }π            beginπ              drexist := true;π              if (r.ax = 0) then ts := 'floppy' else ts := 'hard';π            end;ππ          r.ax := $4409;      { check for local/remote (lan) drv }π          r.bl := drive;π          msdos(r);π          if not odd(r.flags) thenπ            beginπ              drexist := true;π              if ((r.dh and $10) <> 0) then ts := 'remote';π            end;ππ          If DrExist thenπ            beginπ              ts := chr(ord('A')+pred(drive))+':   ' + ts;π              writeln(ts);π            end;π        end;πend.π                                                                                                       9      08-25-9409:11ALL                      GREG VIGNEAULT           VOLUME LABEL Program     SWAG9408    TΣ≥▀    26     ╣   {π>Can someone please tell me how to read the volume label off a hardπ>disk or floppy. I haven't been able to find any information on howπ>to do this.  Thanks for any help you can offer.ππ Here's one way, which is valid for DOS 3.0 or higher...ππ}πPROGRAM VOLAB;                    { Read a disk volume label (TP4+) }π                                  { June 12, 1994. Greg Vigneault   }πUSES  Dos;                              { import MsDos, Registers   }πTYPE  ASCIIZ  = ARRAY [0..255] OF CHAR; { ASCIIZ strings            }πCONST TAB     = #9;                     { ASCII horizontal tab      }πVAR   Drv     : CHAR;                   { drive letter 'A'..'Z'     }π      Volume  : STRING;                 { for volume label          }π      Reg     : Registers;              { to access CPU registers   }ππPROCEDURE Asciiz2TP (AStr:ASCIIZ; VAR Temp:STRING);π  { convert an ASCIIZ (DOS) string to a TP string }π  VAR Index:BYTE; BEGIN  Index := 0;π    WHILE (Index < 255) AND (AStr[Index] <> #0) DO BEGINπ      Temp[Index+1] := AStr[Index];;  INC(Index);π    END{WHILE};;  Temp[0] := CHR(Index);π  END {Asciiz2TP};ππPROCEDURE TP2Asciiz (TStr:STRING; VAR Temp:ASCIIZ);π  { convert a TP string to an ASCIIZ (DOS) string }π  VAR Index:BYTE; BEGIN Index := ORD(TStr[0]);; Temp[Index] := #0;π    WHILE (Index > 0) DO BEGINπ      Temp[Index-1] := TStr[Index];;  DEC(Index);π    END{WHILE};π  END {TP2Asciiz};ππFUNCTION GetVolLabel (Drv:CHAR):STRING;π  VAR Temp:ASCIIZ; Temp2:STRING; Index:BYTE;  seg0,ofs0:WORD;π      DTA : ARRAY [0..127] OF CHAR; BEGIN  Temp2 := '';π    IF Drv IN ['A'..'Z'] THEN BEGIN       { valid drive spec?       }π      Reg.AH := $2F;; MsDos(Reg);         { get current DTA address }π      seg0 := Reg.ES;; ofs0 := Reg.BX;    { save the orig DTA       }π      Reg.DS := SEG(DTA);; Reg.DX := OFS(DTA);  { our local DTA     }π      Reg.AH := $1A;; MsDos(Reg);               { activate our DTA  }π      Temp2 := '?:\*.*';; Temp2[1] := Drv;      { build filespec    }π      TP2Asciiz (Temp2, Temp);                  { xlate to ASCIIZ   }π      Reg.DS := SEG(Temp);; Reg.DX := OFS(Temp);; Reg.CX := 8;π      Reg.AH := $4E;; MsDos(Reg); { label search, then reset DTA... }π      Reg.DS := seg0;; Reg.DX := ofs0;; Reg.AH := $1A;; MsDos(Reg);π      IF NOT ODD(Reg.FLAGS) { no DOS error? }π        THEN FOR Index := $1E TO $2A DO Temp[Index-$1E] := DTA[Index]π        ELSE Temp[0] := #0;             { if no volume label found  }π      Asciiz2TP(Temp, Temp2);           { xlate DOS to TP string    }π      IF (Length(Temp2) > 8) AND (Temp2[9] = '.') { if 8/3 format   }π        THEN Delete (Temp2,9,1);π    END{IF Drv};π    GetVolLabel := Temp2;π  END {GetVolLabel};ππBEGIN {VOLAB: here we go...}ππ  WriteLn;; WriteLn (TAB,'ReadVOL v0.01 Greg Vigneault');; WriteLn;π  REPEATπ    Write (TAB,'Read volume label from which drive [A..Z] ? ');π    Read (Drv);;  Drv := UpCase(Drv);π  UNTIL Drv IN ['A'..'Z'];π  Volume := GetVolLabel (Drv);;  WriteLn;π  IF Length(Volume) <> 0π    THEN WriteLn (TAB,'Volume in drive ',Drv,': is ', Volume)π    ELSE WriteLn (TAB,'No label for volume in drive ',Drv,':');π  WriteLn;ππEND {VOLAB}.π                                                                   10     08-25-9409:12ALL                      JOSE CAMPIONE            Valid Drives             SWAG9408    ±∞WU    12     ╣   πprogram valid_drv;ππuses dos;ππ{ πFunction ready_drives reports as valid only drives that are πready to be read. Findfirst does not cause a critical error even πif a floppy is not ready and in machines with a single floppy πthe prompt to insert a diskette when testing for the B: drive π(from IO.SYS) is avoided by the use of DOS services $4408 and π$440E (requires DOS 3.2 or up). - πJose Campione (1:163/513.3) August 1994 -π} ππfunction ready_drives: string;πvarπ  regs : registers;π  i : byte;π  drs: string;π  sr : searchrec;ππ  function is_last(d:byte):boolean;π  {true if d is the only or the last name assigned to that drive}π  beginπ    regs.ax:= $440E;π    regs.bl:= d;π    msdos(regs);π    is_last:= ((regs.flags and fcarry) = 0) and ((regs.al = 0) or (regs.al = d));π  end;ππ  function is_floppy(d: byte): boolean;π  {true if d is a removable medium}π  beginπ    regs.ax:= $4408;π    regs.bl:= d;π    msdos(regs);π    is_floppy := ((regs.flags and fcarry) = 0) and (regs.ax = 0);π  end;ππbeginπ  drs:= '';π  for i:= 1 to 26 do beginπ    if (not is_floppy(i)) or is_last(i) then beginπ      findfirst(chr(i + 64) + ':\*.*',AnyFile,sr);π      if doserror = 0 then drs:= drs + chr(i + 64);π    end;π  end;π  ready_drives:= drs;πend;ππbeginπ  writeln('drives ready : ',ready_drives);πend.ππ